package gui;

import java.util.Observable;
import java.util.Observer;
import modelcontroller.ChatController;
import modelcontroller.ChatModel;
import modelcontroller.ChatModel.ValueUpdated;
import modelcontroller.Conversation;
import modelcontroller.User;

/**
 *
 * @author Mariam
 */
public final class ChatGUI implements Observer, FromUser, ToUser {

    /**
     * Model associated to the GUI
     */
    protected ChatModel model;
    /**
     * Controller associated to the GUI
     */
    protected ChatController controller;
    /**
     * Window that allows the user to connect to the Chat System
     */
    private ConnectionWindow connectionWindow;
    /**
     * Main window displayed when the user is connected to the Chat System
     */
    private ChatWindow chatWindow;

    /**
     * Contructs the view corresponding to the model.
     * <p>
     * Initially, the view is the connection window.
     *
     * @param model model associated to the GUI
     */
    public ChatGUI(ChatModel model) {
        this.model = model;
        initView();
    }

    /**
     * Sets the controller
     *
     * @param controller controller associated to the GUI
     */
    public void setController(ChatController controller) {
        this.controller = controller;
    }

    /**
     * Signal from the user that he wants to connect to the Chat System
     *
     * @param username the login entered by the local user
     */
    @Override
    public void connect(String username) {
        controller.performConnect(username);
    }

    /**
     * Signal from the user that he wants to disconnect
     */
    @Override
    public void disconnect() {
        controller.performDisconnect();
    }

    /**
     * Signal from the user that he wants to start a dialog with the selected
     * user
     *
     * @param remoteUser the user selected in the list of the connected peers
     */
    @Override
    public void selectUser(User remoteUser) {
        controller.performUserSelected(remoteUser);
    }

    /**
     * Signal from the user that he wants to send a message to a peer user
     *
     * @param username the login of the receiver (remote user)
     * @param message the text that has been typed by the local user
     */
    @Override
    public void sendMessage(String username, String message) {
        controller.performSendMessage(username, message);
    }

    /**
     * Signal from the user that he wants to send a file to a peer user
     *
     * @param filename the name of the file
     * @param filepath the location of the file
     * @param size the size of the file
     */
    @Override
    public void sendFile(String username, String filename, String filepath, long size) {
        controller.performSendFileRequest(username, filename, filepath, size);
    }

    private void initView() {
        displayConnectionWindow();
    }

    private void changeView() {
        if (model.getLocalUserIsConnected()) {
            connected();
        } else {
            disconnected();
        }
    }

    /**
     * Displays the connection window (the user is disconnected)
     */
    @Override
    public void displayConnectionWindow() {
        if (connectionWindow == null) {
            this.connectionWindow = new ConnectionWindow(this);
        }
        this.connectionWindow.setVisible(true);
    }

    private void hideConnectionWindow() {
        if (connectionWindow != null) {
            this.connectionWindow.setVisible(false);
        }
    }

    /**
     * Displays the main chat window (the user is connected)
     */
    @Override
    public void displayChatWindow() {
        if (chatWindow == null) {
            this.chatWindow = new ChatWindow(this);
        }
        this.chatWindow.setVisible(true);
    }

    private void hideChatWindow() {
        if (chatWindow != null) {
            this.chatWindow.setVisible(false);
            this.chatWindow = null;
        }
    }

    private void connected() {
        hideConnectionWindow();
        //displayChatWindow();
        System.exit(0);
    }

    private void disconnected() {
        hideChatWindow();
        displayConnectionWindow();
    }

    /**
     * Displays a new conversation: it opens a new tab in the chat window that
     * will contain the messages exchanged
     *
     * @param conversation the new conversation
     */
    @Override
    public void displayNewConversation(Conversation conversation) {
        chatWindow.openConversation(conversation);
    }

    /**
     * Displays the proposition from a remote user to send a file
     *
     * @param username the login of the sender of the request
     * @param filename the name of the file that is proposed to the local user
     * @return the user's reply: true if he wants to receive the file, false if
     * he refuses
     */
    @Override
    public boolean displayFileRequest(String username, String filename) {
        return chatWindow.displayFileRequest(username, filename);
    }

    /**
     * Displays a file chooser window to ask the user where he wants to
     * locate the file that he is going to receive
     *
     * @return the path (location) where the user wants to download the file
     */
    @Override
    public String displayFileChooser() {
        return chatWindow.displayFilepathRequest();
    }

    /**
     * Displays/refreshes the list of the connected remote users
     */
    @Override
    public void displayUsersList() {
        chatWindow.updateUsersList();
    }

    /**
     * Displays the new text message that has been received
     */
    @Override
    public void displayNewMessage() {
        chatWindow.updateConversationsList();
    }

    @Override
    public void update(Observable o, Object arg) {
        if (arg.equals(ValueUpdated.STATE)) {
            changeView();
        } else if (arg.equals(ValueUpdated.USERSLIST)) {
            if (chatWindow != null) {
                displayUsersList();
            }
        } else if (arg.equals(ValueUpdated.CONVERSATIONSLIST)) {
            if (chatWindow != null) {
                displayNewMessage();
            }
        }
    }
}